﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace TestProject.ModelClasses
{
    public class NodesTree : IDisposable
    {
        public NodesTree()
        {
             _ctx = new CategoriesTreeDataContext();
            _nodes = new HashSet<Node>();
        }

       ~NodesTree()  
       {
           Dispose(false);
       }


        private readonly CategoriesTreeDataContext _ctx;
        private HashSet<Node> _nodes;

        private int _width;
        private int _height;
        private bool _disposed;


        public void LoadFromDB()
        {
            if (Disposed)
            {
                throw new ObjectDisposedException("Object is already disposed");
            }

            HashSet<Node> nodes = new HashSet<Node>();

            IQueryable<Classifier> rootClasses = _ctx.Classifiers.Where(c => c.ParentID == null);
           

            foreach (var cl in rootClasses)
            {
                RecursiveFill(cl, nodes, 1);
                _height++;
            }
         

            _nodes = nodes;
        }


        private void RecursiveFill(Classifier cl, HashSet<Node> nodes, int level)
        {
            Node nd = new Node();
            nd.Name = cl.Name;
            nd.Level = level;
            nodes.Add(nd);

            if (level > _width) _width = level;

            //находим пары
            IQueryable<Pair> pairs = _ctx.Pairs.Where(p => p.ClassifireID == cl.ID)
                .OrderBy(o => o.Key);
            
            

            foreach(var pair in pairs)
            {
                nd.Pairs.Add(new PairItem(pair.Key, pair.Element));
                _height++;
            }

            //найти дочерние записи
            IQueryable<Classifier> childRecords = _ctx.Classifiers.Where(d => d.ParentID == cl.ID)
                .OrderBy(o => o.Name);

            foreach(var c in childRecords)
            {
                RecursiveFill(c, nd.ChildNodes, level + 1);
                _height++;
            }

        }


        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }


        private void Dispose(bool disposing)
        {

            if (!Disposed)
            {
              
                if (disposing)
                {
                    // dispose managed resources
                    _ctx.Dispose();
                }

               //unmanaged resources...
            }
            _disposed = true;
        }




        #region Properies
        public HashSet<Node> Nodes
        {
            get
            {
                return _nodes;
            }
        }

        public int Width
        {
            get
            {
                return _width;
            }
        }

        public int Height
        {
            get
            {
                return _height;
            }
        }

        protected bool Disposed
        {
            get
            {
                lock (this)
                {
                    return _disposed;
                }
            }
        }

       


        #endregion
    }
}